package com.ywk.springCore.aop.simpleAop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**简易切面类
 * @author zbh
 * @date 2022/2/25 14:17
 */
@Component
@Aspect
@Slf4j
public class AopAspectJ {

    /**
     * 必须为final String类型的,注解里要使用的变量只能是静态常量类型的
     */
//    public static final String EDP="execution(* com.ywk.springCore.aop.test.controller.AopTestController..*(..))";
    public static final String EDP="execution(* com.ywk.springCore.aop.test.web.AopTest.aopSimpleApi(..))";

    /**
     * 切面的前置方法 即方法执行前拦截到的方法
     * 在目标方法执行之前的通知
     * @param jp
     */
    @Before(EDP)
    public void doBefore(JoinPoint jp){
        log.info("===========执行前置通知============");
    }

    /**
     * 在方法正常执行通过之后执行的通知叫做返回通知
     * 可以返回到方法的返回值 在注解后加入returning
     * @param jp
     * @param result
     */
    @AfterReturning(value=EDP,returning="result")
    public void doAfterReturning(JoinPoint jp,String result){
        log.info("===========执行后置通知============");
    }

    @Around(EDP)
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable{

        log.info("======执行环绕通知开始=========");
        // 调用方法的参数
        Object[] args = pjp.getArgs();
        // 调用的方法名
        String method = pjp.getSignature().getName();
        // 获取目标对象
        Object target = pjp.getTarget();
        // 执行完方法的返回值
        // 调用proceed()方法，就会触发切入点执行方法
        Object result=pjp.proceed();
        log.info("输出,方法名：" + method + ";目标对象：" + target + ";返回值：" + result);
        log.info("======执行环绕通知结束=========");
        return result;
    }

    /**
     * 在目标方法非正常执行完成, 抛出异常的时候会走此方法
     * @param jp
     * @param ex
     */
    @AfterThrowing(value=EDP,throwing="ex")
    public void doAfterThrowing(JoinPoint jp,Exception ex) {
        System.out.println("===========执行异常通知============");
    }
}
